﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DAL;
using GrupyzServices.Logging;
using GrupyzServices.MailTools;

namespace GrupyzServices.BdAccess
{
    public class OrderRepository : IOrderRepository
    {

        GrupyzEntities _entity;
        ILogger log;

        public OrderRepository()
        {
            _entity = new GrupyzEntities();
            log = new NLogLogger();
        }

        public Order.OrderViewModel FillOrderCliente(int id)
        {
            Cliente cliente = (from x in _entity.Cliente
                              where x.Id == id
                              select x).SingleOrDefault();

            Order.OrderViewModel viewOrder = new Order.OrderViewModel();
            viewOrder.CodPostal = cliente.CodPostal;
            viewOrder.Email = cliente.Email;
            viewOrder.Telefone = cliente.Telefone;
            viewOrder.Morada = cliente.Morada;
            viewOrder.Localidade = cliente.Localidade;

            string[] nome = cliente.Nome.Split(' ');

            if (nome.Length > 1)
            {
                viewOrder.PrimeiroNome = nome.First();
                viewOrder.UltimoNome = nome.Last();
            }
            else { viewOrder.PrimeiroNome = nome.First(); viewOrder.UltimoNome = ""; }

            return viewOrder;
        }

        public bool CreateOrder(ref DAL.Order order, int UserId, decimal Total, int desconto)
        {
            try
            {
                order.Data = DateTime.Now;
                order.IdCliente = UserId;
                order.Total = Total;
                order.Pendente = true;
                order.Concluido = false;
                order.ValorDesconto = desconto;
                _entity.Order.AddObject(order);
                _entity.SaveChanges();

                ClienteRepository cli = new ClienteRepository();
                cli.UpdateClienteOrder(order, UserId);

                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }


        public FinalOrderViewModel ActualizaOrder(DAL.Order order)
        {
            try
            {
                OrderDetail od = (from x in _entity.OrderDetail.Include("Deal")
                                  where x.OrderId == order.Id
                                  select x).SingleOrDefault();

                order.Pendente = true;
                _entity.Order.Attach(order);
                _entity.SaveChanges();

                //Adicionar pontos ao cliente
                ClienteRepository cli = new ClienteRepository();
                string referencia = cli.GetReferencia(order.IdCliente);

                DealRepository dl = new DealRepository();
                bool concluido = dl.ConcluiCompra(od.DealId,od.Quantidade);

                return new FinalOrderViewModel
                {
                    Email = order.Email,
                    Descricao = od.Deal.Texto,
                    Oferta = od.Oferta,
                    Desconto = order.ValorDesconto,
                    EmailDest = od.DadosOferta.EmailDest,
                    Nome = order.PrimeiroNome + " " + order.UltimoNome,
                    NomeDest = od.DadosOferta.NomePara,
                    PrecoUn = od.ValorUn,
                    Qtd = od.Quantidade,
                    Total = order.Total,
                    Referencia = referencia,
                    Concluido = concluido,
                    dealId = od.DealId,
                    OrderId = order.Id,
                    IdPaypal = order.IdPaypal,
                    Pontos = od.Pontos
                };

            }
            catch (Exception)
            {
                return null;
            }
        }


        public DAL.Order GetOrderById(int id)
        {
            return (from x in _entity.Order
                   where x.Id == id
                   select x).SingleOrDefault();
        }


        public bool CreateOrder(ref Order order, int UserId, decimal Total)
        {
            throw new NotImplementedException();
        }

        public void ActualizaOrder(Order order)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<ClienteComprasViewModel> GetOrdersCliente(int IdCliente)
        {
            return from o in _entity.Order
                   join od in _entity.OrderDetail on o.Id equals od.OrderId into g
                   from od in g
                   join d in _entity.Deal on od.DealId equals d.Id into q
                   from d in q
                   select new ClienteComprasViewModel { 
                       Data = o.Data,
                       Descricao = d.Texto,
                       Expira = d.Expira,
                       NomeOferta = od.DadosOferta.NomePara,
                       Oferta = od.Oferta,
                       Quantidade = od.Quantidade,
                       TemDesconto = o.ValorDesconto != null,
                       Total = o.Total,
                       ValorDesconto = o.ValorDesconto,
                       ValorUn = od.ValorUn,
                       DadosOferta = od.DadosOferta
                   };
            
        }


        public bool DeleteOrder(int OrderId)
        {
            try
            {
                var order = GetOrder_OrderDetailById(OrderId);

                _entity.Order.DeleteObject(order);
                
                _entity.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                return false;
            }
        }


        public DAL.Order GetOrder_OrderDetailById(int id)
        {
            return (from x in _entity.Order.Include("OrderDetail")
                    where x.Id == id
                    select x).SingleOrDefault();
        }


        public bool ClienteJaComprou(int idCliente)
        {
            try
            {
                var total = (from x in _entity.Order
                           where x.IdCliente == idCliente
                           && x.Concluido == true
                           select x).Count();

                if (total > 0)
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                return false;
            }
        }


        public bool DealConcluido(FinalOrderViewModel fo)
        {
            try
            {
                DAL.Order order = GetOrder_OrderDetailById(fo.OrderId);

                if (fo.Total != 0)
                {
                    DoCapture capture = new DoCapture();
                    string result = capture.DoCaptureCode(fo.IdPaypal, "Complete", order.Total.ToString(), "", "");
                    if (result == "Success")
                    {
                        //Enviar email
                        Mail.SendMailCompra(order.Email, fo);
                        UpdateCliente(order);

                        order.Pendente = false;
                        order.Concluido = true;
                        _entity.SaveChanges();
                    }
                }
                else
                {
                    //Enviar email
                    Mail.SendMailCompra(order.Email, fo);
                    UpdateCliente(order);

                    order.Pendente = false;
                    order.Concluido = true;
                    _entity.SaveChanges();

                }

                return true;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                return false;
            }
        }

        private void UpdateCliente(DAL.Order order)
        {
            //Adicionar pontos ao cliente
            ClienteRepository cli = new ClienteRepository();
            OrderDetail od = order.OrderDetail.SingleOrDefault();

            if (od.Pontos == 0)
                cli.UpdatePontos(order.IdCliente, true, od.Quantidade);
            else
                cli.UpdatePontos(order.IdCliente, false, od.Pontos);
            
            cli.UpdateReferencias(order.IdCliente, order.Total,ClienteJaComprou(order.IdCliente),true);
        }

        public bool DealPorConcluir(FinalOrderViewModel fo)
        {
            try
            {
                Mail.SendMailCompraPendente(fo.Email, fo);
                DAL.Order order = GetOrderById(fo.OrderId);
                order.Concluido = true;
                _entity.SaveChanges();

                ClienteRepository cli = new ClienteRepository();
                cli.UpdateReferencias(order.IdCliente, order.Total, ClienteJaComprou(order.IdCliente), false);

                return true;
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                return false;
            }
        }


        public OrderPayViewModel GetFinalOrderDetail(int idOrder)
        {
            var tmp = (from x in _entity.OrderDetail.Include("Deal")
                        where x.OrderId == idOrder
                        select x).SingleOrDefault();
            return new OrderPayViewModel
            {
                Descricao = tmp.Deal.Texto,
                Nome = tmp.Deal.Descricao,
                Id = idOrder,
                Quantidade = tmp.Quantidade,
                ValorUn = tmp.ValorUn - tmp.Desconto
            };
        }
    }
}
